package datasource

import (
	"fmt"
	"gitee.com/yanggit123/tool/module"
	"github.com/streadway/amqp"
)

var ch *amqp.Channel

func GetChannel() *amqp.Channel {
	return ch
}

// 初始化数据库
//amqp://root:123456@127.0.0.1:5672/
func EnableRabbitMQ(conf module.RabbitMQConf) (*amqp.Channel, error) {
	conn, err := amqp.Dial(fmt.Sprintf("amqp://%s:%s@%s/%s", conf.UserName, conf.Password, conf.Address, conf.VHost))
	if err != nil {
		return nil, err
	}
	ch, err = conn.Channel()
	if err != nil {
		return nil, err
	}
	return ch, nil
}

//name, kind string, durable, autoDelete, internal, noWait bool, args Table
//名称   类型         持久化  当所有绑定队列都不在使用时，是否自动删除交换器 是否为内部交换机
//开启confirm模式的方法
//生产者通过调用channel的confirmSelect方法将channel设置为Confirm模式，如果没有设置no-wait标志的话，Broker会返回confirm.select-ok表示同意发送者将当前channel信道设置为Confirm模式(从目前RabbitMQ最新版本3.6来看，如果调用了channel.confirmSelect方法，默认情况下是直接将no-wait设置成false的，也就是默认情况下broker是必须回传confirm.select-ok的)。
//创建一个交换机
/*err=ch.ExchangeDeclare("hello.word","topic",true,false,false,true,nil)
  if err!=nil{
     log.Println(err)
  }*/
//创建一个队列Queue
/*q, err := ch.QueueDeclare(
     "hello1", // name
     false,   // durable
     false,   // delete when unused
     false,   // exclusive
     false,   // no-wait
     nil,     // arguments
  )
  if err!=nil{
     log.Panic(err, "Failed to declare a queue")
  }
  log.Println(q)
  //将交换机与队列绑定
  //队列的名称  路由键(topic指接收hello以及word1中的消息)  交换机名称
  //若为#.word、hello.#则表示接收路由键中以正则匹配 可匹配多个单词
  //当路由键为#时相当于群播模式(fanout)
  //当路由键中无*#时只接收该路由键的消息 相当于单播模式(direct)
  err=ch.QueueBind("hello1","hello.#","hello.word",false,nil)
  if err!=nil{
     log.Println(err)
  }*/
//将队列和交换机解绑
//ch.QueueUnbind("hello","hello.word1","hello.word",nil)
/*body := "Hello World!11sss111111"
  err = ch.Publish(
     "hello.word",    // exchange
     "hello.word1", // routing key
     false, // mandatory
     false, // immediate
     amqp.Publishing{
        ContentType: "text/plain",
        Body:        []byte(body),
     })
  log.Printf(" [x] Sent %s", body)
  if err!=nil{
     log.Panic(err, "Failed to publish a message")
  }*/
//消费消息
/*msgs, err := ch.Consume(
"hello", // queue
"",     // consumer
true,   // auto-ack是否自动确认已接收
false,  // exclusive
false,  // no-local
false,  // no-wait
nil,    // args
)
if err!=nil{
log.Println(err, "Failed to register a consumer")
}
forever := make(chan bool)
go func() {
	for d := range msgs {
		log.Printf("Received a message: %s", d.Body)
		rabbitmq.Ack(d.DeliveryTag,false)    //确认消息接收
	}
}()
log.Printf(" [*] Waiting for messages. To exit press CTRL+C")
<-forever
}
**Name**：交换机名称
**Durability**：是否需要持久化，Durable 为持久化，Transient 为不持久化
**Auto Delete**：如果为yes，当最后一个监听被移除后，该队列也会被自动删除
**arguments（其他属性）：**
**1、x-message-ttl：** 消息的过期时间，单位：毫秒
**2、x-expires：** 队列过期时间，队列在多长时间未被访问将被删除，单位：毫秒
**3、x-max-length：** 队列最大长度，超过该最大值，则将从队列头部开始删除消息
**4、x-max-length-bytes：** 队列消息内容占用最大空间，受限于内存大小，超过该值则从队列头部开始删除消息
**5、x-overflow：** 设置队列溢出行为。这决定了当达到队列的最大长度时消息会发生什么。有效值是drop-head、reject-publish或reject-publish-dlx
**6、x-dead-letter-exchange：** 死信交换器名称，过期或被删除（因队列长度超长或因空间超出该值）的消息可指定发送到该交换器中
**7、x-dead-letter-routing-key：** 死信消息路由键，在消息发送到死信交换器时会使用该路由键，如果不设置，则使用消息的原来的路由键值
**8、x-single-active-consumer：** 表示队列是否是单一活动消费者，true时，注册的消费组内只有一个消费者消费消息，其他被忽略，false时消息循环分发给所有消费者(默认false)
**9、x-max-priority：** 队列要支持的最大优先级数;如果未设置，队列将不支持消息优先级
**10、Lazy mode：** 将队列设置为延迟模式，在磁盘上保留尽可能多的消息，以减少RAM的使用;如果未设置，队列将保留内存缓存以尽可能快地传递消息
**11、x-queue-master-locator：** 在集群模式下设置镜像队列的主节点信息

args队列新建参数
x-message-ttl     int //消息存在队列时间ms
x-expires int  //队列过期时间
x-max-length  //queue中可以存储处于ready状态的消息数量
x-max-length-bytes     //queue中可以存储处于ready状态的消息占用的内存空间，单位：字节
x-overflow  //队列的处于ready状态存储消息的个数或消息占用的容量超过设定值后的处理策略
drop-head（删除queue头部的消息）、
reject-publish（最近发来的消息将被丢弃）、
reject-publish-dlx（拒绝发送消息到死信交换器）
类型为quorum 的queue只支持drop-head;
x-dead-letter-exchange     在队列上指定一个Exchange，则在该队列上发生如下情况，
1.消息被拒绝（basic.reject or basic.nack)，且requeue=false
2.消息过期而被删除（TTL）
3.消息数量超过队列最大限制而被删除
4.消息总大小超过队列最大限制而被删除
就会把该消息转发到指定的这个exchange
同时也可以指定一个可选的x-dead-letter-routing-key，表示默认的routing-key，如果没有指定，则使用消息的routeing-key(也跟指定的exchange有关，
如果是Fanout类型的exchange，则会转发到所有绑定到该exchange的所有队列）
（
定义一个队列zhihao.miao.order，其有属性x-dead-letter-exchange是zhihao.miao.exchange.pay，往Exchange名为zhihao.miao.exchange.order中发送消息。

往zhihao.miao.order队列中发送消息，然后拒绝消息



因为其指定了x-dead-letter-exchange是zhihao.miao.exchange.pay，所以会将消息转发到zhihao.miao.exchange.pay，而因为没有指定x-dead-letter-routing-key，所以会使用默认的发送的消息的route key（zhihao.miao.order）进行路由，而我们zhihao.miao.exchange.pay的路由信息如下，所以会将消息转发到zhihao.miao.auto队列中去。
）


*/
